/*********************************************************************
 *
 *  MODULE: MWIN.CPP
 *  AUTHOR: BRIAN M. WORKMAN
 *  START DATE: 3/13/2006 8:41:53 PM
 *
 **********************************************************************/

#include "mwin.h"
MWin::MWin(QWidget *parent, Qt::WFlags flags)
    : QMainWindow(parent, flags) {
    setWindowTitle("MUDtime");
    qApp->setWindowIcon(QIcon(":/ico"));
    QFrame *central = new QFrame(this);
    QVBoxLayout *layout = new QVBoxLayout(central); 
    QFrame *top = new QFrame(this);
    QHBoxLayout *topLayout = new QHBoxLayout(top);

    dateTime = new QDateTimeEdit(this);
    dateTime->setToolTip("Enter the time here in your LOCAL time.");
    QDateTime time;
    dateTime->setWhatsThis("<p>Select the time you wish to convert here.</p>"
        "<p>Ensure that it is <strong>in your LOCAL time</strong>. It will be "
        "converted to an appropriate time behind the scenes for you in order "
        "to generate the time in ThresholdRPG.</p>");
    time = time.currentDateTime();
    
    dateTime->setDateTime(time);
    dateTime->setDisplayFormat("MMM dd yyyy - HH:mm ap");
    topLayout->addWidget(dateTime);

    actFetch = new QAction(QIcon(":/ico"), "Convert", this);
    actFetch->setShortcut(Qt::Key_Return);
    actFetch->setWhatsThis("<p>Click here to fetch the Threshold Time "
    "as converted by http://www.100acre.org/threshtime/threshtime.php.</p>");
    actFetch2 = new QAction(QIcon(":/ico"), "Convert", this);
    actFetch2->setShortcut(Qt::Key_Enter);
    dateTime->addAction(actFetch2);
    fetch = new QToolButton(central);
    fetch->setDefaultAction(actFetch);
    topLayout->addWidget(fetch);

    actCancel = new QAction(QIcon(":/cancel"), "Cancel", this);
    actCancel->setShortcut(tr("Escape"));
    actCancel->setWhatsThis("<p>Click here to cancel the current transaction."
    "</p>");

    config = new QToolButton(central);
    actConfig = new QAction(QIcon(":/config"), "Configure", this);
    actConfig->setWhatsThis("<p>Click here to set various configuration "
    "options for MUDtime.</p>");
    config->setDefaultAction(actConfig);
    topLayout->addWidget(config);

    central->setLayout(layout);
    
    setCentralWidget(central);
    
    topLayout->setMargin(1);
    layout->setMargin(1);
    
    results = new QLineEdit(central);
    results->setReadOnly(true);
    results->setWhatsThis("<p>The results of your time conversion will "
    "appear here.</p>");
    
    layout->addWidget(top);
    layout->addWidget(results);
    statusBar();
    statusBar()->showMessage("Not connected.");
    data = new QBuffer(this);
    http = new QHttp(this);
    
    connect(actFetch, SIGNAL(triggered()), this, SLOT(doFetch()));
    connect(actFetch2, SIGNAL(triggered()), this, SLOT(doFetch()));
    connect(actConfig, SIGNAL(triggered()), this, SLOT(doConfig()));
    connect(http, SIGNAL(requestFinished(int, bool)),
            this, SLOT(httpRequestFinished(int, bool)));
    connect(http, SIGNAL(responseHeaderReceived(const QHttpResponseHeader &)),
            this, SLOT(readResponseHeader(const QHttpResponseHeader &)));
    connect(actCancel, SIGNAL(triggered()), this, SLOT(cancelDownload()));
    connect(http, SIGNAL(stateChanged(int)), this, SLOT(stateChanged(int)));
    
    statusBar()->setSizeGripEnabled(false);
    setBaseSize(200,75);
    setMaximumSize(baseSize());
    enableInput(true);
    readSettings();
}

bool MWin::isStandardTime(QDateTime now) {
    QList<QString> dates;
    dates << "04022006|10292006" 
          << "03112007|11042007"
          << "03092008|11022008"
          << "03082009|11012009"
          << "03142010|11072010"
          << "03132011|11062011";

    for(int i = 0; i < dates.count(); i++) {
        QList<QString> d = dates[i].split("|");
        QDateTime d_begin = QDateTime::fromString(QString("%1%2")
            .arg(d[0]).arg("0159"), "MMddyyyyHHmm");            
        QDateTime d_end = QDateTime::fromString(QString("%1%2")
            .arg(d[1]).arg("0159"), "MMddyyyyHHmm");
        if(now.date().year() == d_begin.date().year()) {
            if(now <= d_begin || now > d_end) {
                return false;
            } else return true;
        }
    }
    QMessageBox::warning(this, "MUDtime", 
        QString("No appropriate daylight savings time information "
        "found for year %1.\nAssuming standard time.").arg(now.date().year()));
    return true;
}

void MWin::doFetch() {
    int hour = 60 * 60;
    QDateTime dtime = dateTime->dateTime().toTimeSpec(Qt::UTC);
    int secs = dtime.time().second(); 
    dtime = dtime.addSecs(-secs);
    
    bool standard = isStandardTime(dtime);
    if(!standard) dtime.addSecs(-hour);

    QDate date = dtime.date();
    QTime time = dtime.time();
     
    QString tmp_url = 
            QString("http://www.100acre.org/threshtime/threshtime.php?rhour=%1&rminute=%2&rmonth=%3&rday=%4&ryear=%5&rtimezone=%6")
            .arg(time.hour())
            .arg(time.minute())
            .arg(date.month()-1)
            .arg(date.day())
            .arg(date.year())
            .arg(0);
    QUrl url(tmp_url);
    http->setHost(url.host(), url.port() != -1 ? url.port() : 80);
    if(m_proxy)
        http->setProxy(m_proxy_address, m_proxy_port, m_proxy_username,
                   m_proxy_password);
    if (!url.userName().isEmpty())
        http->setUser(url.userName(), url.password());

    httpRequestAborted = false;
    data = new QBuffer(this);
    if(data->open(QIODevice::WriteOnly)) {
        httpGetId = http->get(tmp_url, data);
    }
    enableInput(false);
    results->clear();
}

void MWin::doConfig() {
    window = new ConfigDialog(this);
    window->enableProxy(m_proxy);
    window->setProxyAddress(m_proxy_address);
    window->setProxyPort(m_proxy_port);
    window->setProxyUsername(m_proxy_username);
    window->setProxyPassword(m_proxy_password);
    window->setAutoClipboard(m_auto_clipboard);
    if(window->exec() == QDialog::Accepted) {
        m_proxy = window->proxy();
        m_proxy_address = window->proxyAddress();
        m_proxy_port = window->proxyPort();
        m_proxy_username = window->proxyUsername();
        m_proxy_password = window->proxyPassword();
        m_auto_clipboard = window->autoClipboard();
        writeSettings();
    }
    delete window;
}

void MWin::readResponseHeader(const QHttpResponseHeader &responseHeader)
{
    if (responseHeader.statusCode() != 200) {
        QMessageBox::information(this, tr("MUDtime"),
                                 tr("Download failed: %1.")
                                 .arg(responseHeader.reasonPhrase()));
        httpRequestAborted = true;
        enableInput(true);
        http->abort();
        return;
    }
}

void MWin::httpRequestFinished(int requestId, bool error)
{

    data->close();
    if (httpRequestAborted) {
        return;
    }

    if (requestId != httpGetId) {
        return;
    }
    if (error) {
        QMessageBox::information(this, tr("MUDtime"),
                                 tr("Download failed: %1.")
                                 .arg(http->errorString()));
                                 
    } else {
        data->open(QIODevice::ReadOnly);
        QString t = data->data();
        int l = t.indexOf("<b>") + 3;
        int r = t.indexOf("</b>");
        t = t.mid(l, r-l);

        l = t.indexOf("</u>")+4;
        r = t.length() - 1;
        t = t.mid(l, r);
        t = t.trimmed();
        
        QString toll;
        QString date;
        int colon;
        
        colon = t.indexOf(":");
        toll = t.mid(0,colon);
        date = t.right(t.length()-(colon+4)).trimmed();
        
        switch(toll.toInt()) {
            case 11: case 12: case 13: toll.append("th"); break;
            default:
                if(toll.left(1) == "0") toll = toll.right(1);
                if(toll.right(1) == "1") toll.append("st");
                else if(toll.right(1) == "2") toll.append("nd");
                else if(toll.right(1) == "3") toll.append("rd");
                else toll.append("th");
                break;
        }
        QString resultats = QString("%1 toll of %2").arg(toll).arg(date); 
        results->setText(resultats);
        if(m_auto_clipboard) {
            QClipboard *clip = QApplication::clipboard();
            clip->setText(resultats);
        }        
    }
    enableInput(true);
}

void MWin::cancelDownload()
{
    enableInput(true);
    httpRequestAborted = true;
    http->abort();
}

void MWin::stateChanged(int s) {
     QString state;
     switch(s) {
         case QHttp::Unconnected: state = "Not connected."; break;
         case QHttp::HostLookup: state = "Looking up host..."; break;
         case QHttp::Connecting: state = "Connecting..."; break;
         case QHttp::Sending: state = "Sending data..."; break;
         case QHttp::Reading: state = "Reading data..."; break;
         case QHttp::Connected: state = "Connected."; break;
         case QHttp::Closing: state = "Closing..."; break;
     }
     statusBar()->showMessage(state);
}

void MWin::enableInput(bool yn) {
    if(yn) {
        fetch->removeAction(actCancel);
        fetch->setDefaultAction(actFetch);
    } else {
        fetch->removeAction(actFetch);
        fetch->setDefaultAction(actCancel);
    }
    dateTime->setEnabled(yn);
    actConfig->setEnabled(yn);
}

void MWin::readSettings() {
    QSettings settings("Ellenia Group", "MUDtime");
    m_proxy = settings.value("useproxy", false).toBool();
    m_proxy_address = settings.value("proxy", "").toString();
    m_proxy_port = settings.value("port", 80).toInt();
    m_proxy_username = settings.value("username", "").toString();
    m_proxy_password = settings.value("password", "").toString();
    m_auto_clipboard = settings.value("autoclipboard", false).toBool();
}

void MWin::writeSettings() {
    QSettings settings("Ellenia Group", "MUDtime");
    settings.setValue("useproxy", m_proxy);
    settings.setValue("proxy", m_proxy_address);
    settings.setValue("port", m_proxy_port);
    settings.setValue("username", m_proxy_username);
    settings.setValue("password", m_proxy_password);
    settings.setValue("autoclipboard", m_auto_clipboard);
}

ConfigDialog::ConfigDialog(QWidget *parent)
    : QDialog(parent) {
    ui.setupUi(this);
}

void ConfigDialog::enableProxy(bool yn) {
    ui.groupProxy->setChecked(yn);
}

void ConfigDialog::setProxyAddress(QString address) {
    ui.edAddress->setText(address);
}

void ConfigDialog::setProxyPort(int port) {
    ui.edPort->setText(QString("%1").arg(port));
}

void ConfigDialog::setProxyUsername(QString user) {
    ui.edUsername->setText(user);
}

void ConfigDialog::setProxyPassword(QString password) {
    ui.edPassword->setText(password);
}

void ConfigDialog::setAutoClipboard(bool yn) {
    ui.chkClipboard->setChecked(yn);
}

bool ConfigDialog::proxy() const { return ui.groupProxy->isChecked(); }
QString ConfigDialog::proxyAddress() const { return ui.edAddress->text(); }
int ConfigDialog::proxyPort() const { return ui.edPort->text().toInt(); }
QString ConfigDialog::proxyUsername() const { return ui.edUsername->text(); }
QString ConfigDialog::proxyPassword() const { return ui.edPassword->text(); }
bool ConfigDialog::autoClipboard() const { return ui.chkClipboard->isChecked(); }
